/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mabi.frontend.appbuilder.modulemanager;

import com.mabi.modular.runtime.module.RuntimeModuleFactory;
import com.mabi.frontend.FrontEndApp;
import com.mabi.modular.install.modules.IModuleDefinition;
import com.mabi.modular.runtime.module.AbstractMabiModule;
import com.mabi.modular.runtime.module.RuntimeMabiModule;
import com.mabi.modular.runtime.module.contributions.views.ViewImpl;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.NamingException;


/**
 *
 * @author User
 */
public class ModuleManager {

    private FrontEndApp frontEndApp;
    private static ModuleManager instance;
    private List<AbstractMabiModule> installedModules;

    /**
     * Singleton enforcer
     * @param app
     * @return 
     */
    public static ModuleManager getDefault(FrontEndApp app) {
        if (null == instance) {
            instance = new ModuleManager(app);
        }
        return instance;
    }

    /**
     * Constructor
     * @param app 
     */
    private ModuleManager(FrontEndApp app) {
        frontEndApp = app;
    }

    /**
     * Installs the modules into the application
     */
    public void loadModules() throws NamingException {
        List<IModuleDefinition> lInstalledModules = null;
        lInstalledModules = getInstalledModules();

        for (IModuleDefinition module : lInstalledModules) {
            prepareModuleForLoading(module);
            RuntimeMabiModule runtimeModule;
            try {
                runtimeModule = RuntimeModuleFactory.getDefault().buildRuntimeModule(module);
                frontEndApp.loadModule(runtimeModule);
                //installViews(module);
            } catch (InstantiationException ex) {
                Logger.getLogger(ModuleManager.class.getName()).log(Level.SEVERE, null, ex);
                continue;
            } catch (IllegalAccessException ex) {
                Logger.getLogger(ModuleManager.class.getName()).log(Level.SEVERE, null, ex);
                continue;
            }
        }
    }

    /**
     * Returns a collection of IModuleDefinition installed during application deployment
     * @return
     * @throws NamingException 
     */
    private static List<IModuleDefinition> getInstalledModules() throws NamingException {
        ModuleLoader moduleLoader = new ModuleLoader();
        List<IModuleDefinition> loadModules = moduleLoader.discoverInstalledModules();
        return loadModules;
    }

    /**
     * Installs autoload modules views
     * @param module
     */
    private void installViews(IModuleDefinition module) {
        List<Class<ViewImpl>> views = module.getViews();

        for (Class<ViewImpl> viewClass : views) {
            try {
                ViewImpl viewInstance = viewClass.newInstance();
                viewInstance.setModuleName(module.getModuleName());
                System.out.println("VIEW CAPTION = " + viewInstance.getCaption());
                if (viewInstance.isAutoLoad()) {
                    try {
                        frontEndApp.addView(viewInstance);
                    } catch (Exception ex) {
                        Logger.getLogger(ModuleManager.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            } catch (InstantiationException ex) {
                Logger.getLogger(ModuleManager.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(ModuleManager.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void prepareModuleForLoading(IModuleDefinition module) {
        if (this.installedModules == null) {
            this.installedModules = new ArrayList();
        }

        //Inject the application context to the module
        //module.setUpContext(frontEndApp.getAppContext(), frontEndApp);

        //Injects the application to the module in order that the 
        //module code gets access to the application api
        module.setAppication(frontEndApp);

        //Initializes the module
        module.initializeModule();


        //this.installedModules.add(module);
    }
}
